﻿import cocos
import random
from cocos.sprite import Sprite
from cocos.actions import MoveBy, Repeat, Delay, CallFunc
from cocos.layer import Layer, ColorLayer
from cocos.director import director
from cocos.text import Label
from cocos.collision_model import CollisionManagerGrid
from cocos.euclid import Vector2
from pyglet.window import key
import pyglet

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
PLAYER_SPEED = 300
BULLET_SPEED = 500
ENEMY_SPEED = 150
ENEMY_SPAWN_INTERVAL = 1.0
MAX_ENEMIES = 10

# 初始化碰撞管理器
cm = None

class Player(Sprite):
    def __init__(self):
        super().__init__('player.png')  # 玩家飞船图片
        self.position = SCREEN_WIDTH // 2, 50
        self.scale = 0.5
        self.speed = PLAYER_SPEED
        self.cshape = cm.AARectShape(
            Vector2(self.position[0], self.position[1]),
            self.width // 2,
            self.height // 2
        )
    
    def update(self, dt):
        # 更新碰撞形状
        self.cshape.center = Vector2(self.position[0], self.position[1])
    
    def move_left(self):
        self.x = max(self.width // 2, self.x - self.speed * director.dt)
    
    def move_right(self):
        self.x = min(SCREEN_WIDTH - self.width // 2, self.x + self.speed * director.dt)

class Bullet(Sprite):
    def __init__(self, x, y):
        super().__init__('bullet.png')  # 子弹图片
        self.position = x, y
        self.speed = BULLET_SPEED
        self.cshape = cm.AARectShape(
            Vector2(self.position[0], self.position[1]),
            self.width // 2,
            self.height // 2
        )
    
    def update(self, dt):
        # 向上移动
        self.y += self.speed * dt
        
        # 更新碰撞形状
        self.cshape.center = Vector2(self.x, self.y)
        
        # 如果离开屏幕，移除子弹
        if self.y > SCREEN_HEIGHT + self.height:
            self.kill()

class Enemy(Sprite):
    def __init__(self):
        super().__init__('enemy.png')  # 敌人飞船图片
        self.position = random.randint(50, SCREEN_WIDTH - 50), SCREEN_HEIGHT + 50
        self.speed = random.randint(ENEMY_SPEED - 50, ENEMY_SPEED + 50)
        self.cshape = cm.AARectShape(
            Vector2(self.position[0], self.position[1]),
            self.width // 2,
            self.height // 2
        )
    
    def update(self, dt):
        # 向下移动
        self.y -= self.speed * dt
        
        # 更新碰撞形状
        self.cshape.center = Vector2(self.x, self.y)
        
        # 如果离开屏幕，移除敌人
        if self.y < -self.height:
            self.kill()
            game_layer.score -= 1

class GameLayer(Layer):
    is_event_handler = True  # 启用事件处理
    
    def __init__(self):
        super().__init__()
        
        # 游戏状态
        self.score = 0
        self.game_over = False
        
        # 创建碰撞管理器
        global cm
        cm = CollisionManagerGrid(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, 50, 50)
        
        # 创建玩家
        self.player = Player()
        self.add(self.player)
        
        # 创建分数显示
        self.score_label = Label(
            f"分数: {self.score}",
            font_name="Arial",
            font_size=24,
            x=20,
            y=SCREEN_HEIGHT - 30,
            anchor_x="left",
            anchor_y="top"
        )
        self.add(self.score_label)
        
        # 创建敌人生成器
        self.schedule(self.spawn_enemy)
        
        # 安排更新函数
        self.schedule(self.update)
    
    def spawn_enemy(self, dt):
        if len(self.get_children()) < MAX_ENEMIES + 5:  # +5 包括玩家、子弹等
            enemy = Enemy()
            self.add(enemy)
    
    def update(self, dt):
        if self.game_over:
            return
        
        # 更新碰撞管理器
        cm.clear()
        
        # 添加所有可碰撞对象
        for node in self.get_children():
            if hasattr(node, 'cshape'):
                cm.add(node)
                if isinstance(node, (Bullet, Enemy)):
                    node.update(dt)
        
        # 检测子弹与敌人的碰撞
        for bullet in self.get_children():
            if isinstance(bullet, Bullet):
                for enemy in cm.objs_colliding(bullet):
                    if isinstance(enemy, Enemy):
                        self.score += 1
                        self.score_label.element.text = f"分数: {self.score}"
                        bullet.kill()
                        enemy.kill()
        
        # 检测玩家与敌人的碰撞
        for enemy in cm.objs_colliding(self.player):
            if isinstance(enemy, Enemy):
                self.game_over = True
                self.show_game_over()
    
    def on_key_press(self, key, modifiers):
        if key == key.SPACE:
            # 发射子弹
            bullet = Bullet(self.player.x, self.player.y + self.player.height // 2)
            self.add(bullet)
    
    def on_key_release(self, key, modifiers):
        pass
    
    def show_game_over(self):
        # 显示游戏结束文本
        game_over_label = Label(
            "游戏结束!",
            font_name="Arial",
            font_size=48,
            x=SCREEN_WIDTH // 2,
            y=SCREEN_HEIGHT // 2,
            anchor_x="center",
            anchor_y="center"
        )
        self.add(game_over_label)
        
        # 显示最终分数
        score_label = Label(
            f"最终分数: {self.score}",
            font_name="Arial",
            font_size=36,
            x=SCREEN_WIDTH // 2,
            y=SCREEN_HEIGHT // 2 - 60,
            anchor_x="center",
            anchor_y="center"
        )
        self.add(score_label)
        
        # 显示重新开始提示
        restart_label = Label(
            "按R键重新开始",
            font_name="Arial",
            font_size=24,
            x=SCREEN_WIDTH // 2,
            y=SCREEN_HEIGHT // 2 - 120,
            anchor_x="center",
            anchor_y="center"
        )
        self.add(restart_label)
        
        # 监听R键重新开始
        self.on_key_press = self.restart_on_key_press
    
    def restart_on_key_press(self, key, modifiers):
        if key == key.R:
            # 重新开始游戏
            director.replace(cocos.scene.Scene(GameLayer()))

class BackgroundLayer(ColorLayer):
    def __init__(self):
        super().__init__(30, 30, 60, 255)  # 深蓝色背景
        self.schedule(self.update)
        self.stars = []
        
        # 创建星星
        for _ in range(100):
            x = random.randint(0, SCREEN_WIDTH)
            y = random.randint(0, SCREEN_HEIGHT)
            size = random.randint(1, 3)
            speed = random.uniform(10, 50)
            self.stars.append({
                'x': x, 
                'y': y, 
                'size': size, 
                'speed': speed
            })
    
    def update(self, dt):
        # 更新星星位置
        for star in self.stars:
            star['y'] -= star['speed'] * dt
            if star['y'] < 0:
                star['y'] = SCREEN_HEIGHT
                star['x'] = random.randint(0, SCREEN_WIDTH)
    
    def draw(self):
        super().draw()
        
        # 绘制星星
        for star in self.stars:
            pygame.draw.circle(
                self.batch, 
                (255, 255, 255), 
                (star['x'], star['y']), 
                star['size']
            )

if __name__ == "__main__":
    # 初始化导演
    director.init(
        width=SCREEN_WIDTH,
        height=SCREEN_HEIGHT,
        caption="太空射击游戏",
        resizable=True
    )
    
    # 创建场景
    scene = cocos.scene.Scene()
    
    # 添加背景层
    scene.add(BackgroundLayer(), z=0)
    
    # 添加游戏层
    scene.add(GameLayer(), z=1)
    
    # 运行游戏
    director.run(scene)